package com.ceo.common.query;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ceo.common.utils.StringKit;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


public class QueryParameter<T> {
    private static final Logger logger = LoggerFactory.getLogger(QueryParameter.class);
    private Map<String, Object> _params = new HashMap<String, Object>();
    public Map<String, QueryCondition> _conditions = new HashMap<String, QueryCondition>();
    protected String sortField;
    protected String sortOrder;
    private int pageIndex = 1;
    private int pageSize = 20;


    public Map<String, Object> get_params() {
        return _params;
    }

    public void set_params(Map<String, Object> _params) {
        if (_params == null)
            return;
        this._params.clear();
        for (String key : _params.keySet()) {
            Object obj = _params.get(key);
            this.addParamter(key, obj);
        }
        //this._params = _params;
    }

    public Map<String, QueryCondition> get_conditions() {
        return _conditions;
    }

    public void set_conditions(Map<String, QueryCondition> _conditions) {
        this._conditions = _conditions;
    }

    public int getPageIndex() {
        return pageIndex;
    }

    public void setPageIndex(int pageIndex) {
        this.pageIndex = pageIndex;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }


    /**
     * 设定分页参数
     *
     * @param pageSize  每页条数
     * @param pageIndex 起始页数
     * @return Pager
     */
    public void setPager(int pageIndex, int pageSize) {
        this.pageIndex = pageIndex;
        this.pageSize = pageSize;
    }


    /**
     * 获取所有查询条件的name集合
     *
     * @return
     */
    public Set<String> getParamNamesOld() {
        return this._params.keySet();
    }

    /**
     * 添加查询参数
     *
     * @param p_name  参数名称
     * @param p_value 参数值
     * @return 是否添加成功
     */
    public QueryParameter addParamter(String p_name, Object p_value) {
        this._params.put(p_name.trim(), p_value);
        return this;
    }

    /**
     * 添加查询参数,重载的方法
     *
     * @param p_name    参数名称
     * @param p_value   参数值
     * @param condition 应用的查询表达式
     */
    public QueryParameter addParamter(String p_name, Object p_value, QueryCondition condition) {
        addParamter(p_name, p_value);
        _conditions.put(p_name.trim(), condition);
        return this;
    }

    /**
     * 移除查询参数
     *
     * @param p_name 参数名称
     */
    public Object removeParamter(String p_name) {
        _conditions.remove(p_name);
        return _params.remove(p_name);
    }

//    /**
//     * 获取参数值
//     *
//     * @param p_name 参数名称
//     * @return
//     */
//    public Object getParam(String p_name) {
//        return _params.get(p_name);
//    }

//    /**
//     * 设定查询参数集合
//     *
//     * @param params 参数集合
//     */
//    public void setParams(Map<String, Object> params) {
//        if (params == null)
//            return;
//        this._params.clear();
//        for (String key : params.keySet()) {
//            Object obj = params.get(key);
//            this.addParamter(key, obj);
//        }
//
//    }

    public void clearParams() {
        this._params.clear();
        this._conditions.clear();
    }

//    /**
//     * 获取所有的查询参数
//     *
//     * @return
//     */
//    public Map<String, Object> getParams() {
//        return _params;
//    }

    /**
     * 获取排序字段
     *
     * @return 排序的字段名
     */
    public String getSortField() {
        if (StrUtil.isNotBlank(sortField))
            return sortField;
        else
            return "";
    }

    /**
     * 获取排序字段带模式名
     *
     * @param translation 模式名
     * @return 带模式名的排序字段名
     */
    public String getSortField(String translation) {
        if (StrUtil.isNotBlank(sortField)) {
            if (StrUtil.isBlank(translation))
                translation = "";
            else
                translation = translation + ".";
            String[] fields = sortField.split(",");
            StringBuilder sb = new StringBuilder();
            for (String field : fields)
                sb.append("," + translation + field);

            return sb.toString().replaceFirst(",", "");
        } else
            return "";
    }

    /**
     * 获取排序字符串
     *
     * @param translation 表的别名(如:原始sql select * from table_temp t;则此时你的translation 传 t)
     * @return 若没有排序字段则返会空字符串, 否则返回order by xxx asc/desc
     */
    public String getOrderStr(String translation) {
        if (StrUtil.isBlank(sortField))
            return "";
        return " order by " + getSortField(translation) + " " + getSortOrder();
    }

    public void setSortField(String sortField) {
        this.sortField = sortField;
    }

    public String getSortOrder() {
        if (StrUtil.isNotBlank(sortOrder))
            return sortOrder;
        else
            return "asc";
    }

    public void setSortOrder(String sortOrder) {
        this.sortOrder = sortOrder;
    }

    /**
     * 添加查询参数的表达式
     *
     * @param param 应用表达式的列/属性名
     * @param qc    表达式
     */
    public void addCondition(String param, QueryCondition qc) {
        if (StrUtil.isNotBlank(param))
            _conditions.put(param.trim(), qc);
    }

    /**
     * 获取查询参数的表达式
     *
     * @param param 应用表达式的列/属性名
     * @return 表达式(若此列不存在则返回null)
     */
    public QueryCondition getCondition(String param) {
        if ((_params.get(param) == null || StrUtil.isNotEmpty(_params.get(param).toString())) && _conditions.get(param) == null)
            return QueryCondition.equal;
        return _conditions.get(param);
    }

    /**
     * 将查询参数和查询表达式处理成sql的where条件表达式语句
     *
     * @param translation 模式名(可空)
     * @return sql的where表达式语句(不包含where关键字)
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public String transformationCondition(String translation) {
        if (StrUtil.isBlank(translation))
            translation = "";
        else
            translation = translation + ".";
        StringBuffer sb = new StringBuffer(" 1=1 ");
        for (String key : _params.keySet()) {
            Object value = _params.get(key);
            if (value == null)
                continue;
            //若值为数组或集合时将多个值处理成,号分割的字符串
            if (value != null && (value.getClass().isArray() || value instanceof Collection)) {
                if (value.getClass().isArray())//数组类型转换
                    value = StringKit.arrayToString((Object[]) value, ",");
                else if (value instanceof List) {
                    value = StringKit.arrayToString(((List<Object>) value).toArray(), ",");//集合类型转换
                } else if (value instanceof Set) {
                    value = StringKit.arrayToString(((Set) value).toArray(), ",");//集合类型转换
                }
            }
            if (StringKit.isBlank(value))
                continue;
            value = value.toString().replaceAll("'", "");
            QueryCondition qc = _conditions.get(key);
            qc = qc == null ? QueryCondition.equal : qc;
            if (key.contains("$"))
                key = key.substring(0, key.indexOf("$"));

            String valueTag = "'";
            if (key.indexOf("!") == 0) {
                valueTag = "";
                key = key.replace("!", "");
            }
            if (qc == QueryCondition.equal)
                sb.append(" and " + translation + key + " = " + valueTag + value + valueTag);
            else if (qc == QueryCondition.not_equal)
                sb.append(" and (" + translation + key + " != " + valueTag + value + valueTag + " or " + translation + key + " is null)");
            else if (qc == QueryCondition.large)
                sb.append(" and " + translation + key + " > " + valueTag + value + valueTag);
            else if (qc == QueryCondition.large_equal)
                sb.append(" and " + translation + key + " >= " + valueTag + value + valueTag);
            else if (qc == QueryCondition.small)
                sb.append(" and " + translation + key + " < " + valueTag + value + valueTag);
            else if (qc == QueryCondition.small_equal)
                sb.append(" and " + translation + key + " <= " + valueTag + value + valueTag);
            else if (qc == QueryCondition.like_anywhere)
                sb.append(" and " + translation + key + " like '%" + value + "%'");
            else if (qc == QueryCondition.like_end)
                sb.append(" and " + translation + key + " like '%" + value + "'");
            else if (qc == QueryCondition.like_start)
                sb.append(" and " + translation + key + " like '" + value + "%'");
            else if (qc == QueryCondition.range) {
                String s = ((String) value).split("~")[0];
                String e = ((String) value).split("~")[1];
                if (StrUtil.isNotBlank(s))
                    sb.append(" and " + translation + key + " >= '" + s + "'");
                if (StrUtil.isNotBlank(e))
                    sb.append(" and " + translation + key + " <= '" + e + "'");
            } else if (qc == QueryCondition.in) {
                String in_str = StringKit.change_in(value.toString());
                if (StrUtil.isNotBlank(in_str))
                    sb.append(" and " + translation + key + " in (" + in_str + ")");
            } else if (qc == QueryCondition.not_in) {
                String in_str = StringKit.change_in(value.toString());
                if (StrUtil.isNotBlank(in_str))
                    sb.append(" and " + translation + key + " not in (" + in_str + ")");
            } else if (qc == QueryCondition.if_null) {
                if (value.equals("1"))
                    sb.append(" and (" + translation + key + " is null or " + translation + key + "='')");
                else if (value.equals("0"))
                    sb.append(" and " + translation + key + " is not null");
            } else if (qc == QueryCondition.between) {
                String[] a = value.toString().split(",");
                sb.append(" and " + translation + key + " BETWEEN '" + a[0] + "' AND '" + a[1] + "'");
            } else if (qc == QueryCondition.not_between) {
                String[] a = value.toString().split(",");
                sb.append(" and " + translation + key + " NOT BETWEEN '" + a[0] + "' AND '" + a[1] + "'");
            } else if (qc == QueryCondition.large_small) {
                String[] a = value.toString().split(",");
                if (StrUtil.isNotBlank(a[0]))
                    sb.append(" and " + translation + key + " >= '" + a[0] + "'");
                if (StrUtil.isNotBlank(a[1]))
                    sb.append(" and " + translation + key + " <= '" + a[1] + "'");
            }

        }
        return sb.toString();
    }

    public Page<T> getPage(){
       return new Page<T>(getPageIndex(), getPageSize());
    }

    public QueryWrapper<T> createWrapper() {
        return createWrapper(null,null);
    }

    public QueryWrapper<T> createWrapper(String translation) {
        return createWrapper(null,translation);
    }

    /**
     * 创建QueryWrapper
     *
     * @param queryWrapper
     * @param translation
     * @return QueryWrapper
     */
    public QueryWrapper<T> createWrapper(QueryWrapper<T> queryWrapper, String translation) {
        if (StrUtil.isBlank(translation))
            translation = "";
        else
            translation = translation + ".";

        if (queryWrapper == null) {
            queryWrapper = new QueryWrapper<>();
        }
        for (String k : _params.keySet()) {
            Object v = _params.get(k);
            if (StrUtil.isNotBlank(v.toString())) {
                QueryCondition exp = _conditions.get(k);
                exp = exp == null ? QueryCondition.equal : exp;
                String key = StringKit.HumpToUnderline(k);
                key = translation + key;
                switch (exp) {
                    case equal:// 等于=
                        queryWrapper.eq(key, v);
                        break;
                    case not_equal:// 不等于<>
                        queryWrapper.ne(key, v);
                        break;
                    case like_anywhere:// 模糊查询 LIKE
                        queryWrapper.like(key, v);
                        break;
                    case like_start:// 以什么结尾的查询
                        queryWrapper.likeLeft(key, v);
                        break;
                    case like_end:// 以什么开头
                        queryWrapper.likeRight(key, v);
                        break;
                    case small:// 小于
                        queryWrapper.gt(key, v);
                        break;
                    case large:// 大于
                        queryWrapper.lt(key, v);
                        break;
                    case large_equal:// 大于等于 >=
                        queryWrapper.ge(key, v);
                        break;
                    case small_equal:// 小于等于 <=
                        queryWrapper.le(key, v);
                        break;
                    case in:
                        if (v != null && !Strings.isNullOrEmpty(v.toString()))
                            queryWrapper.in(key, v.toString().split(","));
                        break;
                    case not_in:
                        if (v != null && !Strings.isNullOrEmpty(v.toString()))
                            queryWrapper.notIn(key, v.toString().split(","));
                        break;
                    case between://
                        String[] values = v.toString().split(",");
                        if (values.length > 1) {
                            String strDateFormat = "yyyy-MM-dd";
                            SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
                            try {
                                Date endDate = sdf.parse(values[1]);
                                Calendar c = Calendar.getInstance();
                                c.setTime(endDate);

                                c.add(Calendar.DAY_OF_MONTH, 1);
                                endDate = c.getTime();
                                queryWrapper.between(key, sdf.parse(values[0]), endDate);
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                        break;
                    case not_between://
                        String[] values_t = v.toString().split(",");
                        if (values_t.length > 1) {
                            String strDateFormat = "yyyy-MM-dd";
                            SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
                            try {
                                Date endDate = sdf.parse(values_t[1]);
                                Calendar c = Calendar.getInstance();
                                c.setTime(endDate);

                                c.add(Calendar.DAY_OF_MONTH, 1);
                                endDate = c.getTime();
                                queryWrapper.notBetween(key, sdf.parse(values_t[0]), endDate);
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                        break;
                    case timebetween://
                        String[] values1 = v.toString().split(",");
                        if (values1.length > 1) {
                            String strDateFormat = "yyyy-MM-dd HH:mm:ss";
                            SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
                            try {
                                Date endDate = sdf.parse(values1[1]);
                                Calendar c = Calendar.getInstance();
                                c.setTime(endDate);
                                endDate = c.getTime();
                                queryWrapper.between(key, sdf.parse(values1[0]), endDate);
                            } catch (ParseException e) {
                                logger.error(e.getMessage());
                            }
                        }
                        break;
                    case large_small:
                        String[] a = v.toString().split(",");
                        if (StrUtil.isNotBlank(a[0]))
                            queryWrapper.ge(key, a[0]);
                        if (StrUtil.isNotBlank(a[1]))
                            queryWrapper.le(key, a[1]);
                        break;
                    case range:
                        String[] s = v.toString().split("~");
                        if (StrUtil.isNotBlank(s[0]))
                            queryWrapper.ge(key, s[0]);
                        if (StrUtil.isNotBlank(s[1]))
                            queryWrapper.le(key, s[1]);
                    default:
//                        throw new PlatformException()
                        break;
                }
            }
        }
        return queryWrapper;
    }
}
